[HNOI2007]紧急疏散

2020-02-02
HNOI

题意

在$n*m$的矩阵内有空地、墙和门

初始时空地均站有一人;门一个时刻只能疏散一人;墙不能走

每个时刻人可以往上下左右四个方向动,问最小时间

题解

按照时间分层建图

门->T的边每次流量是1,空地->门不用控制,相当于在门里等着升天

枚举答案,直接在残余网络上跑

最坏情况下时间是400,超过就是不可能

调试记录

没加当前弧

数组小了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cstring>
#define ID(i, j) ((i - 1) * m + j)
#define P ((tim - 1) * N)
const int maxn = 80005;
const int S = 0;
const int T = 80001;
const int INF = 0x3f3f3f3f;
const int dx[4] = {0, 0, 1, -1};
const int dy[4] = {1, -1, 0, 0};
using namespace std;
struct E{
int to, nxt, f;
}e[maxn << 4]; int head[maxn], tot = 1;
void addedge(int u, int v, int f){
e[++tot].to = v, e[tot].nxt = head[u], e[tot].f = f;
head[u] = tot;
}
void ins(int u, int v, int f){
addedge(u, v, f); addedge(v, u, 0);
}
int dep[maxn], now[maxn];
bool bfs(){
queue <int> q; while (!q.empty()) q.pop(); q.push(S);
memset(dep, 0, sizeof dep); dep[S] = 1; memcpy(now, head, sizeof now);
while (!q.empty()){
int cur = q.front(); q.pop();
for (int i = head[cur]; i; i = e[i].nxt){
if (e[i].f > 0 && dep[e[i].to] == 0){
dep[e[i].to] = dep[cur] + 1;
q.push(e[i].to);
}
}
}
return dep[T] > 0;
}
int dfs(int cur, int Max){
if (cur == T) return Max;
int flow = 0;
for (int i = now[cur]; i; i = e[i].nxt){
int v = e[i].to; now[cur] = i;
if (e[i].f > 0 && dep[v] == dep[cur] + 1){
int tmp = dfs(v, min(Max - flow, e[i].f));
flow += tmp;
e[i].f -= tmp;
e[i ^ 1].f += tmp;
if (flow == Max) return flow;
}
}
return flow;
}
int maxflow = 0;
void Dinic(){
while (bfs())
maxflow += dfs(S, INF);
}
int n, m, N, cnt; char g[25][25];
int main(){
// freopen("1.in", "r", stdin);
scanf("%d%d", &n, &m); N = n * m;
for (int i = 1; i <= n; i++) scanf("%s", g[i] + 1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++){
if (g[i][j] == '.') ins(S, ID(i, j), 1), ++cnt;
}
int tim = 0;
while (++tim){
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++){
if (g[i][j] == 'X') continue;
if (g[i][j] != 'D'){
for (int k = 0; k < 4; k++){
int tx = i + dx[k], ty = j + dy[k];
if (tx < 1 || tx > n || ty < 1 || ty > m || g[tx][ty] == 'X') continue;
ins(ID(i, j) + P, ID(tx, ty) + tim * N, INF);
}
}
if (g[i][j] == 'D') ins(ID(i, j) + tim * N, T, 1);
ins(ID(i, j) + P, ID(i, j) + tim * N, INF);
}
Dinic();
if (maxflow == cnt) break;
if (tim > 400){
puts("impossible");
return 0;
}
} printf("%d\n", tim);
return 0;
}